<?php
abstract class Slash_ACL_Property_Principal
implements Sabre_DAV_Property_IHref 
{
	/*
	 * Supports property principals, owner principals, group principals etc.
	 */

	/**
	 * Serializes the property into a DOMElement.
	 *
   * Copyright © 2010 Jack Cleaver
   * 
   * This plugin provides functionality added by CalDAV (RFC 4791)
   * It implements new reports, and the MKCALENDAR method.
   *
   * This file is part of Slash.
   *
   * Slash is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * Slash is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with Slash.  If not, see <http://www.gnu.org/licenses/>.
	 */
	public abstract function serialize(Sabre_DAV_Server $server, DOMElement $node);
	
	/*
	 * Convert the principal to a string form suitable for use as an array index.
	 * property principals are represented as property:{namespace-uri}local-name
	 * href principals look like "href:/path/to/principal/resource 
	 * others are represented as "all:", "authenticated:" etc.
	 * 
	 * The princstr key is as follows:
   * self:
   * authenticated:
   * unauthenticated:
   * all:
   * href:/principals/xyz
   * property:sp{http://jackpot.uk.net/slash}Author
   */
	public abstract function toString();
	
	static function unserialize(DOMElement $princElement)
	{
		$typeElement = $princElement->getElementsByTagName("*")->item(0);
		Slash_Debug::debug("ACL_Property_Principal unserialize: typeElement nodename=" . $typeElement->nodeName);
		$strType = Sabre_DAV_XMLUtil::toClarkNotation($typeElement);

		if ($strType=='{DAV:}href')
		{
			$href = Slash_ACL_Property_Href::unserialize($typeElement);
			return new Slash_ACL_Property_HrefPrincipal($href);
		} else if ($strType == '{DAV:}all')
		{
			return new Slash_ACL_Property_AllPrincipal();
		} else if ($strType == '{DAV:}self')
		{
			return new Slash_ACL_Property_SelfPrincipal();
		} else if ($strType == '{DAV:}authenticated')
		{
			return new Slash_ACL_Property_AuthenticatedPrincipal();
		} else if ($strType == '{DAV:}unauthenticated')
		{
			return new Slash_ACL_Property_UnauthenticatedPrincipal();
		} else if ($strType == '{DAV:}property')
		{
			$propElement = $typeElement->getElementsByTagName("*")->item(0);
			return Slash_ACL_Property_PropertyPrincipal::unserialize($propElement);
		} else {
			Slash_Debug::debug("Property Principal unserialize: Unknown Principal type: $strType");
		}
	}
	
	public function getHref()
	{
		return null;
	}


	/*
	 * Return true if this Principal is the same as the referenced Principal.
	 * 
	 * Override for Principal types whose equivalence depends on more than their class.
	 */
	public function equals(Slash_ACL_Property_Principal $princ)
	{
		$result = false;
		if (get_class($this) == get_class($princ))
		{
			$result = true;
		}
		return $result;
	}

	/*
	 * Return true if this (property) principal includes the property Principal 
	 * $princ.
	 * This method is called by the Acl property's grantsPrivilege() method, 
	 * and the principal it passes to this method is made from the current user, or
	 *  else is UNAUTHENTICATED.
	 */  
	public function includesPrincipal(Slash_ACL_Property_Principal $princ, Sabre_DAV_FSExt_Node $resourceNode)
	{
		//This principal always includes itself.
		//The "all" principal includes any principal.
		if ($this->equals($princ) || $this instanceof Slash_ACL_Property_AllPrincipal)
		{
			return true;
		}		
		return false;
	}
	

	/*
	 * Construct a Principal from the notation created by toString().
	 * @param string $str
	 */
	public static function fromString($str)
	{
		Slash_Debug::debug("ACL_Property_Principal fromString: $str");
		$parts = explode(":", $str, 2);
		$typeName = $parts[0];
		if (isset($parts[1]))
		{
			$extra = $parts[1];
		}
		$princ;
		if ($typeName == "href")
		{
			$princ = new Slash_ACL_Property_HrefPrincipal($extra);
		} else if ($typeName == "property")
		{
			if (preg_match("/{([^}]+)}(.+)/", $extra, $matches) > 0)
			{
				$princ = new Slash_ACL_Property_PropertyPrincipal($matches[1], $matches[2]);
			} else {
				throw new Sabre_DAV_Exception("Invalid PropertyPrincipal string representation: $str");
			}
		} else if ($typeName == "authenticated")
		{
			$princ = new Slash_ACL_Property_AuthenticatedPrincipal();
		} else if ($typeName == "unauthenticated")
		{
			$princ = new Slash_ACL_Property_UnauthenticatedPrincipal();
		} else if ($typeName == "self")
		{
			$princ = new Slash_ACL_Property_SelfPrincipal();
		} else if ($typeName == "all")
		{
			$princ = new Slash_ACL_Property_AllPrincipal();
		} else {
			throw new Sabre_DAV_Exception("Invalid string representation of Principal: $str");
		}
		return $princ;
	}
		
}